import got from "got";
import queryString from "query-string";
import config from "../config.js";
import NodeRSA from "node-rsa";
import { log, logError, sleep } from "./util.js";
import { cookieJar } from "./cookie.js";

export const getPayUrl = async (url) => {
  const res = await got({
    url,
    followRedirect: false,
    cookieJar,
    headers: {
      "User-Agent": config.userAgent,
    },
  });
  if (res.statusCode !== 302) {
    throw new Error("获取重定向链接失败");
  }
  const location = res.headers.location;
  return location;
};

export const report = async (params) => {
  try {
    await got({
      url: "https://tscenter.alipay.com/home/pc.htm",
      searchParams: params,
      headers: {
        Referer: params.url,
        "User-Agent": config.userAgent,
      },
      cookieJar,
    });
  } catch (err) {
    logError("report Error", err);
  }
};

export const getPayMethod = async (url, payUrl, params) => {
  const res = await got({
    url: "https://mclient.alipay.com/wapcashier/api/cashierMain.json",
    method: "POST",
    json: {
      h5_request_token: params.h5_request_token,
      // "query_params": "cc=y&session=RZZFB02mNXrBf1AeFmBmGLNLwXVhEOmobilecashierRZZFB02&utdid=XW5zxZX2ANMDALAKuZBiLPy+&ltAndroidSdkLoadingVersion=Y&init_from=SDKLite&awid=RZ42mUVHHDR8G7UaiztWPGXseTtvBpmobileclientgwRZ42&route_pay_from=h5&tid=742a795a2056c170abdc539a1a06357dd62ca5caa28822a157bdf2a315178bfd",
      query_params: url.split("?")[1],
      app_name: params.app_name,
      tid: params.tid,
      targetDispatchSystem: "unitradeprod",
      serverParams: params.serverParams,
      cookieToken: params.cookieToken,
      device: {
        userAgent: config.userAgent,
        screenWidth: 375,
        screenHeight: 667,
        hardwareConcurrency: 8,
      },
      supportWriteCookie: true,
      t: Date.now(),
      h5payClientId: config.h5payClientId,
      lastReferer: "",
    },
    headers: {
      Referer: payUrl,
      "User-Agent": config.userAgent,
    },
    cookieJar,
  });
  const body = JSON.parse(res.body);
  return body;
};

export const getPassword = (pwd, modulus, exponent = "010001") => {
  if (typeof pwd !== "string" || pwd.length < 6) {
    throw new Error("Password must be a string with at least 6 characters.");
  }
  const key = new NodeRSA();
  key.importKey(
    {
      n: Buffer.from(modulus, "hex"),
      e: Buffer.from(exponent, "hex"),
    },
    "components-public",
  );
  key.setOptions({ encryptionScheme: "pkcs1" });

  let spwd = [];
  for (let i = 0; i < pwd.length; i++) {
    // 确保遍历6个字符
    const charBuffer = Buffer.from(pwd[i], "utf-8"); // 处理字符转换
    const encrypted = key.encrypt(charBuffer, "base64");
    spwd.push(encrypted);
  }
  return spwd.join(",");
};

export const pay = async (url, password) => {
  const payUrl = await getPayUrl(url);
  got({
    url: payUrl,
    headers: {
      Referer: url,
      "User-Agent": config.userAgent,
    },
    cookieJar,
  }).catch((err) => logError("请求重定向支付链接失败", err.message));
  const params = queryString.parseUrl(payUrl).query;
  const payMethod = await getPayMethod(url, payUrl, params);
  log(`加载支付方式结果：${JSON.stringify(payMethod)}`);
  const bizData = payMethod.data.bizData;
  if (!bizData?.combinationIndex) {
    const errMsg = bizData?.msg || "获取支付方式失败";
    throw new Error(errMsg);
  }

  report({
    apikey: "h5cashier",
    token: "",
    userid: payMethod.data.userId,
    sid: payMethod.data.mcSessionId,
    href: url,
  }).catch((err) => logError("report失败", err.message));

  const postBody = {
    server_param: payMethod.params.server_param,
    contextId: payMethod.params.contextId,
    cookieToken: payMethod.params.cookieToken,
    pageToken: "",
    refreshNoAuth: "Y",
    // spwd: getPassword(password, payMethod.data.rsaPubKey),
    // pwd: getPassword(password, payMethod.data.rsaPubKey),
    combinationIndex: bizData.combinationIndex,
    // "ua": "Q0F4Zj2HwBBTiq5nOyjYHNuOkIrdPcEo.bPyBm4w8Rv0Y.x8k0LL12JMKcHI6kxI_V2_qwFlNyk4SohlJuECMk23cUpFyYzy4V_tMgV_nKaUXERTVt2RYprBQyZ1Vd3zeXNLKlQEJVYufqSrsYfFQfFwyiMf0fXSckchtNN6H9UjCx0ND62.RcA8f3Ln4_z8P5Men1CnLPpulhCQ2YkBPGiXS2F9BvLp2bK7kfB2eohlhedEDidJW4JNP4.qAgUr2qE5neYDff8FwJgHrOhu5xnl.0bOftwazX.dEZ_3uU8qzNPq4RmReIOjdpsrquwKhz_XTyRbxAMqPm2CiRzjWEY3fkhUFSwiIg0U4QGzl.nEdila7gGbHXPPXtrLfKP8wd37GuqqwLhqw0wDRi7sJMQT3_mhA.5amzQ1Vbk4Z.bzPz5SWk6vbhLQatiqFy39I6JfTWTRgrtxum0r9oGCvxcPWl9nKcBxTiRAjh.KrZEXwlc3ByZIXz8rCzRivrvB0bZVskWQAXi11GO40uqUsC6myrZdIcReh27ou79ZJrqg_UxRzywKtFvKJZH6pYu6U_OO0Y7Ue162nmhs25yjBCH83nTo49eTVkihUBbSSLzZA0eiNsXHjPIcTxImQC.Aowxyrb6SFi2R4S36KAN7YxX7KZNmghRFlby4oxVb8VhLhsN5Z0Gl0p8_pNqdfuFRhW7L_XiY9HBTE5.PA1EkGZnWD0D7AvENBQd_oaoxOGHCUO9RJBYfKsb6aqtYI4vgVzGmKm.hWpiQmjJf00S0j1tx8ZNWH4usKOYExLcJSxy2qMpiNVGHHIi3so28IQPrZgoCuINErjQEg_.hEt4J5F9hjo1V.6vP5zIF.SL8byUB2NGhQGEZaXxVfYbmJVuwMhxejtREpcfSsguFFgUu1RIc7yyYXYO89tRXBsXr9RR.wuelBqce8aumd4OGES7PkJMJAhYS9tz8WVrSOJaw2Yg3hszEx1DW.DnU.ScvNjgd9U3LydFe2tIrvCY9IZQy80QfXQUtO7.CA7aTWrtaCbRfiWBWw9jYtZ8fOxqEgOlVC9nsLzkAi_dotpwuB5VCbt6erhgoqm3C6pwZf1W29h.TKHTjn33e4PkUJeCeg.R_8m7GyACfN6_OefOLHtbEI5zKtCNEQu.fE1XJZXHTwToqYIrj4TZyeMVnPIVqIlywXVZfHouOGH2bDDZWlnRG07tXVG9FWN_Hqzwi_3WG3Jl8FsO9X78.m01nD8OqLNI",
    ua: "",
    t: Date.now(),
    h5payClientId: config.h5payClientId,
    lastReferer: "",
  };

  const passwordKey = password.length === 6 ? "spwd" : "pwd";
  postBody[passwordKey] = getPassword(password, payMethod.data.rsaPubKey);

  // console.log(postBody);
  const res = await got({
    url: "https://mclient.alipay.com/wapcashier/api/cashierPay.json",
    method: "POST",
    json: postBody,
    headers: {
      Referer: url,
      "User-Agent": config.userAgent,
    },
    cookieJar,
  });
  // console.log(res);
  log("支付结果", res.body);
  const body = JSON.parse(res.body);
  const errMsg = body?.errorMsg || body?.data?.wnd?.msg || "";
  if (errMsg.includes("系统繁忙") || errMsg.includes("无法获取付款结果")) {
    log(`${errMsg}, 加载支付方式判断结果`);
    await sleep(2000);
    const retryPayMethod = await getPayMethod(url, payUrl, params);
    const resultMsg = retryPayMethod?.data?.bizData?.msg || "";
    log(`重试加载支付方式结果：${JSON.stringify(retryPayMethod)}`);
    if (resultMsg.includes("订单已付款成功")) {
      return body;
    } else {
      throw new Error(`${errMsg},${resultMsg}`);
    }
  }
  if (!body.success) {
    throw new Error(errMsg || "支付请求失败");
  }
  if (res.body.includes("短信校验码")) {
    throw new Error("需要输入验证码");
  }
  if (body?.data?.controlType === "verify_check") {
    throw new Error("弹窗确认验证码");
  }
  if (errMsg) {
    throw new Error(body?.data?.wnd?.msg);
  }
  if (body?.data?.wnd?.act?.syncMutex) {
    throw new Error("支付被风控");
  }
  return body;
};
